package com.gitee.wsl.android.ext.math

import android.graphics.Point
import android.graphics.PointF
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.add
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.sub
import kotlin.math.atan
import kotlin.math.cos
import kotlin.math.sin


/**
 * Returns list of points
 * @param listSize: Size of total number of points needed.
 * @param start: X values to start from. ex: 50 to 100
 * @param maxRange: Max range of Y values
 */
fun Math.getLineChartData(listSize: Int, start: Int = 0, maxRange: Int): List<Point> {
    val list = arrayListOf<Point>()
    for (index in 0 until listSize) {
        list.add(
            Point(
                index,
                (start until maxRange).random()
            )
        )
    }
    return list
}

/**
 * Returns list of points
 * @param listSize: Size of total number of points needed.
 * @param start: X values to start from. ex: 50 to 100
 * @param maxRange: Max range of Y values
 */
fun Math.getRandomPoints(listSize: Int, start: Int = 0, maxRange: Int): List<Point> {
    val list = arrayListOf<Point>()
    for (index in 0 until listSize) {
        list.add(
            Point(
                index,
                (start until maxRange).random()
            )
        )
    }
    return list
}

//依圆心坐标，半径，扇形角度，计算出扇形终射线与圆弧交叉点的xy坐标
fun Math.calcArcEndPointXY(
    cirX: Float,
    cirY: Float,
    radius: Float,
    cirAngle: Float
): PointF {
    var mPosX = 0.0f
    var mPosY = 0.0f
    var mPointF = PointF(0f,0f)

    if (cirAngle.compareTo(0.0f) == 0 || radius.compareTo(0.0f) == 0) {
        return mPointF
    }

    //将角度转换为弧度
    var arcAngle: Float = (Math.PI * Math.div(cirAngle, 180.0f)).toFloat()
    if (arcAngle.compareTo(0.0f) == -1) {
        mPosY = 0.0f
        mPosX = mPosY
    }
    if (cirAngle.compareTo(90.0f) == -1) {
        mPosX = Math.add(cirX, cos(arcAngle) * radius)
        mPosY = Math.add(cirY, sin(arcAngle) * radius)
    } else if (cirAngle.compareTo(90.0f) == 0) {
        mPosX = cirX
        mPosY = Math.add(cirY, radius)
    } else if (cirAngle.compareTo(90.0f) == 1 &&
        cirAngle.compareTo(180.0f) == -1
    ) {
        arcAngle = (Math.PI * Math.sub(180f, cirAngle) / 180.0f).toFloat()
        mPosX = Math.sub(cirX, cos(arcAngle) * radius)
        mPosY = Math.add(cirY, sin(arcAngle) * radius)
    } else if (cirAngle.compareTo(180.0f) == 0) {
        mPosX = cirX - radius
        mPosY = cirY
    } else if (cirAngle.compareTo(180.0f) == 1 &&
        cirAngle.compareTo(270.0f) == -1
    ) {
        arcAngle = (Math.PI * Math.sub(cirAngle, 180.0f) / 180.0f).toFloat()
        mPosX = Math.sub(cirX, cos(arcAngle) * radius)
        mPosY = Math.sub(cirY, sin(arcAngle) * radius)
    } else if (cirAngle.compareTo(270.0f) == 0) {
        mPosX = cirX
        mPosY = Math.sub(cirY, radius)
    } else {
        arcAngle = (Math.PI * Math.sub(360.0f, cirAngle) / 180.0f).toFloat()
        mPosX = Math.add(cirX, cos(arcAngle) * radius)
        mPosY = Math.sub(cirY, sin(arcAngle) * radius)
    }
    mPointF.x = mPosX
    mPointF.y = mPosY
    return mPointF
}

/**
 * Get the point of intersection between circle and line.
 * 获取通过指定圆心，斜率为lineK的直线与圆的交点。
 *
 * @param pMiddle
 * The circle center point.
 * @param radius
 * The circle radius.
 * @param lineK
 * The slope of line which cross the pMiddle.
 * @return
 */
fun Math.getIntersectionPoints(
    pMiddle: PointF, radius: Float,
    lineK: Double?
): Pair<PointF,PointF> {


    //高中数学：几何
    val arctan: Float
    val xOffset: Float
    val yOffset: Float
    if (lineK != null) {
        // 计算直角三角形边长
        // 余切函数（弧度）
        arctan = atan(lineK).toFloat()
        // 正弦函数
        xOffset = (sin(arctan.toDouble()) * radius).toFloat()
        // 余弦函数
        yOffset = (cos(arctan.toDouble()) * radius).toFloat()
    } else {
        xOffset = radius
        yOffset = 0f
    }
    val points0 = PointF(pMiddle.x + xOffset, pMiddle.y - yOffset)
    val points1 = PointF(pMiddle.x - xOffset, pMiddle.y + yOffset)
    return points0 to points1
}

fun PointF.degree(toPintF:PointF):Float{
    return Math.getDegree(this.x,this.y,toPintF.x,toPintF.y).toFloat()
}

fun PointF.radian(toPintF:PointF):Float{
    return Math.getRadian(this.x,this.y,toPintF.x,toPintF.y).toFloat()
}